﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace RayOptimizer
{
    public partial class MainForm : Form
    {
        private List<Town> townList;
        private double length;

        public double Length
        {
            get 
            { 
                return length; 
            }
            
            set 
            { 
                length = value;
                Text = value.ToString();
            }
        }

        public MainForm()
        {
            InitializeComponent();
            
            townList = new List<Town>();
            length = 0;
        }

        private void FileAnalyzer(string path)
        {
            foreach (string line in File.ReadAllLines(path))
            {
                string[] temp = line.Split(' ');
                townList.Add(new Town(Int64.Parse(temp[0]), Int64.Parse(temp[1])));
            }
        }

        private double CalculateDistance(int townIndex1, int townIndex2)
        {
            return (Math.Sqrt(Math.Pow((townList[townIndex1].X - townList[townIndex2].X), 2) + Math.Pow((townList[townIndex1].Y - townList[townIndex2].Y), 2)));
        }

        private void ConnectTowns(int townIndex1, int townIndex2)
        {
            if (townList[townIndex1].Connected || townList[townIndex2].Connected)
            {
                richTextOutput.AppendText(townIndex1.ToString() + ' ' + townIndex2.ToString() + '\n');
                townList[townIndex1].Connected = true;
                townList[townIndex2].Connected = true;
                Length += CalculateDistance(townIndex1, townIndex2);
            }
        }

        private int FindCentralmostTown()
        {
            int retValue = -1;
            double lowestLength = -1;

            for (int i = 0; i < townList.Count; i++)
            {
                double currentLength = -1;

                for (int j = 0; j < townList.Count; j++)
                {
                    if (i != j)
                    {
                        currentLength += CalculateDistance(i, j);
                    }
                }

                if (lowestLength == -1 || currentLength < lowestLength)
                {
                    lowestLength = currentLength;
                    retValue = i;
                }
            }

            return retValue;
        }

        private int FindNearestNeighbor(int townIndex)
        {
            int retValue = -1;
            double lowestLength = -1;

            for (int i = 0; i < townList.Count; i++)
            {
                double currentLength = -1;

                if (i != townIndex && !townList[i].Connected)
                {
                    currentLength = CalculateDistance(townIndex, i);
                    
                    if (lowestLength == -1 || currentLength < lowestLength)
                    {
                        lowestLength = currentLength;
                        retValue = i;
                    }
                }                
            }

            return retValue;
        }

        private void ConnectTownsDirectly()
        {
            int town = FindCentralmostTown();
            townList[town].Connected = true;

            while (town != -1)
            {
                int newTown = FindNearestNeighbor(town);

                if (newTown != -1)
                {
                    ConnectTowns(town, newTown);
                }
                town = newTown;
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                openFileDialog.ShowDialog();
                FileAnalyzer(openFileDialog.FileName);
                ConnectTownsDirectly();
            }
            catch
            {
                Close();
            }
        }
    }
}
